iT邦幫忙

2026 iThome 鐵人賽

DAY 28
0

動筆前先答(兩題)

1.【模擬面試追問|規格與驗收】 舊 App 有三條「把東西交給另一個人」的流程:

  • 任務轉手(使用者對使用者):發起方送出請求,可以是「把單給對方」或「向對方要單」,送出後只顯示一次後端訊息就結束。接收方要進列表頁或下拉重新整理才看得到請求,每一列有「確認」「拒絕」兩顆鈕。沒有推播、沒有輪詢,發起方不會知道結果。確認/拒絕鈕不看請求的狀態,一律顯示。後端的狀態列舉裡有「取消」,但 App 裡沒有任何地方會發出取消。
  • 貨品 QR 交接(使用者對使用者):
    • 發起方:選交接類型 → 向後端取一組交接碼,碼附帶相對效期秒數 → 先呼叫「刷出」,把勾選的貨品從自己名下移走 → 成功後才產生 QR 給對方看。
    • 接收方:掃 QR 或手動輸入碼 → 用碼向後端取回貨品清單 → 逐支掃條碼比對 → 數量相符才呼叫「刷入」。
    • 發起方的 QR 對話框只有一顆「OK」,按了就關。倒數到期時只是把畫面改成「過期」,真正擋下來的是接收方收到後端的過期錯誤。
  • 交給合作店家:拍照、上傳、送出,單方面完成,對方不用確認。

狀態分散在三個地方:

  • 事件鏈:兩個一次性事件加一個要手動清空的 LiveData。
  • 碼與截止時間:放在 ViewModel 的私有欄位,當作兩次 API 呼叫之間的旁路。
  • 接收方取回的清單:放在 Activity 的欄位。

流程相關的布林旗標約 7 個,相關畫面都沒有實作 onSaveInstanceState。

你在文章裡寫了一句「我把 QR 交接改成一個 sealed 狀態機」。面試官順著往下問,不看下面的大綱,依序回答:

  1. 從發起方的角度把 QR 交接畫成狀態:列出每個狀態的名稱、帶的資料,以及能離開它的事件。「已刷出、等對方刷入」是不是一個狀態?發起方怎麼知道對方刷入了:輪詢、推播,還是根本不知道?選一個,並說出它的代價。

  2. 順序是「先刷出、後給碼」。對方一直沒來刷入,貨品在誰名下?碼過期之後呢?發起方的 App 這時該顯示什麼、能做什麼:重取碼、撤回,還是什麼都不做?撤回需要後端提供什麼?如果後端沒有撤回 API,你的驗收條件要怎麼寫才誠實?

  3. 截止時刻是「收到回應當下的手機時鐘+相對秒數」。手機時鐘慢五分鐘,或使用者在倒數途中改了系統時間,倒數會怎樣?你會用哪一個時鐘?把「過期」寫成一條驗收條件,要讓注入時鐘的 JVM 測試抓得到這個邊界。

  4. 接收方遇到下面四個情境:

    • 掃到一個已過期、或已經被別人用掉的碼。
    • 同一個碼掃兩次。
    • 比對到一半網路斷了。
    • 按下「完成」後還沒收到回應,程序就被殺掉。

    逐一說明:狀態機停在哪個狀態、使用者看到什麼、重送安不安全,以及冪等性要靠誰保證。

  5. 任務轉手的發起方「送出就結束」,接收方的鈕「不看狀態」。面試官問「這也算握手嗎?」你怎麼回?新設計要不要讓發起方看得到對方的回應?要的話,後端最少要多給什麼?

最後回答:這些狀態裡,哪些是 App 自己的狀態,哪些其實是後端的狀態、App 只是負責顯示?程序被回收後,你要還原哪些?

我的回答:(待補)

2.【決策邊界|架構論述】 同一個交接流程,狀態機要放在哪裡?三個選項:

  • (A) 只放 ViewModel:sealed TransferUiState,在 onEvent 裡用 when 直接轉移。「數量相符才能送出」「過期了不能再用」這類規則也寫在 ViewModel。
  • (B) 領域狀態機放 domain:一個純 Kotlin 的轉移函式 (State, Event) -> Transition(newState, effects),沒有 Android 依賴。ViewModel 只負責執行 effect(呼叫 API、計時),再把領域狀態映射成 UiState。
  • (C) 後端是唯一真相:App 不建狀態機,只照後端回傳的交接紀錄狀態畫畫面;每次進頁或下拉時重新查。

不看下面的大綱,依序回答:

  1. 三條流程(任務轉手、QR 交接、交給店家)要共用一個狀態機或泛型框架,還是各寫各的?什麼條件下你會抽出共用的部分?寫出你「不抽」的門檻。
  2. Day 16 討論過 use case 層「何時值得」。用同一把尺量:交接的哪幾條規則值得放進 domain(數量相符、過期判定、哪些狀態可以重送),哪幾條留在 ViewModel 就夠?如果某條規則後端已經在擋,App 端再寫一份的代價是什麼、好處又是什麼?
  3. 計時與副作用:在 (B) 裡,倒數、輪詢、API 呼叫由誰執行?轉移函式本身要不要知道「現在幾點」?寫出讓 (B) 的轉移函式能用純 JVM 測試、而且不需要 runTest 的設計條件。
  4. 程序被回收與 SavedStateHandle:(A)、(B)、(C) 各要存什麼才還原得回來?「接收方比對到一半的清單」要不要存?存了的話,會不會跟後端的實際狀態對不上?對不上時以誰為準?
  5. Day 26–28 是可裁切項。如果 Day 28 只能交一條流程的一半,你選哪一條、哪一半?最低驗收是什麼?什麼證據(客服紀錄、後端卡住的交接筆數、使用者回報)會讓你從 (C) 換到 (B),或從 (B) 退回 (C)?

最後用兩句話收尾:你的結論,以及你願意承認的代價。

我的回答:(待補)


上一篇
Day 27|前景定位服務與 Compose 的溝通
下一篇
Day 29|回顧:模組依賴圖、指標、沒做到的事
系列文
從 Fragment 到 Compose — 老 Android App 重寫的架構取捨 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言